package apobates.gui.formatter.richedit;

import apobates.gui.formatter.service.RecentExecutorService;
import apobates.gui.formatter.storage.RecentRecord;
import javafx.beans.binding.Bindings;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.TransferMode;
import org.fxmisc.richtext.InlineCssTextArea;
import org.kordamp.ikonli.javafx.FontIcon;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 左侧的区域(待格式化内容)编辑器
 */
public class SourceAreaHelper {
    /**
     * 清除内容
     */
    private static final BiConsumer<String,InlineCssTextArea> emptyEditorFun = (content, leftSource)->leftSource.clear();
    /**
     * 设置内容
     */
    private static final BiConsumer<String,InlineCssTextArea> putEditorFun = (content, leftSource)->leftSource.appendText(null==content?"":content);
    /**
     * 往剪切板中设置内容: 复制
     */
    private static final Consumer<InlineCssTextArea> clipboardToFun = (leftSource)->{
        if(null!=leftSource.getText()) {
            Clipboard clipboard = Clipboard.getSystemClipboard();
            ClipboardContent cc = new ClipboardContent();
            cc.putString(leftSource.getText());
            clipboard.setContent(cc);
        }
    };
    /**
     * 从剪切板中获取内容: 粘贴
     */
    private static final Function<DataFormat, Object> clipboardFromFun = (mode)->{
        return Clipboard.getSystemClipboard().getContent(mode);
    };

    /**
     * 初始化
     * @param leftSource
     * @param contentChangeFun 内容变化消费函数
     */
    public static void initializeEditor(InlineCssTextArea leftSource, Consumer<String> contentChangeFun) {
        leftSource.setWrapText(true);
        leftSource.appendText("");
        // 提示框
        // 过渡提示
        final Label placeholderLabel = new Label();
        placeholderLabel.textProperty()
                .bind(Bindings.when(leftSource.wrapTextProperty())
                        .then("拖拽文件或打开Json文件或获取URL的响应内容")
                        .otherwise("点击:格式化"));
        leftSource.setPlaceholder(placeholderLabel);
        // 文件拖拽
        leftSource.setEditable(true);
        leftSource.setOnDragOver((e)->{
            if (e.getGestureSource() != leftSource && e.getDragboard().hasFiles()) {
                e.acceptTransferModes(TransferMode.COPY_OR_MOVE);
                // System.out.println("[RL][Drop-init] file is json:"+e.getDragboard().getFiles().get(0).getName().toLowerCase());
                final boolean isAccepted = e.getDragboard().getFiles().get(0).getName().toLowerCase().endsWith(".json");
                if (isAccepted) {
                    leftSource.setStyle("-fx-border-color: green;"
                            + "-fx-border-width: 2;"
                            + "-fx-border-style: solid;");
                } else {
                    leftSource.setStyle("-fx-border-color: red;"
                            + "-fx-border-width: 2;"
                            + "-fx-border-style: solid;");
                }
            }
            e.consume();
        });
        // ::RichTextFX::输入框件值变化
        leftSource.textProperty().addListener((obs, oldText, newText) -> {
            contentChangeFun.accept(newText);
        });
        // 绑定右键菜单
        // leftSource.setContextMenu(buildContextMenu(leftSource));
    }

    /**
     * 绑定右键基础菜单
     * @param leftSource 左侧的编辑区
     * @param formatFun 内容格式化消费函数
     * @param saveFileFun 内容保存消费函数
     * @param exitAppFun 退出消费函数
     */
    public static void buildBasicContextMenu(
            final InlineCssTextArea leftSource,
            Consumer<String> formatFun,
            Consumer<String> saveFileFun,
            Consumer<Void> exitAppFun){
        ContextMenu contextMenu = buildBasicRightMenu(leftSource, formatFun, saveFileFun, exitAppFun);
        leftSource.setContextMenu(contextMenu);
    }

    /**
     * 绑定右键全菜单
     * @param leftSource 左侧的编辑区
     * @param recentExecutorService
     * @param formatFun 内容格式化消费函数
     * @param saveFileFun 内容保存消费函数
     * @param exitAppFun 退出消费函数
     */
    public static void buildFullContextMenu(
            final InlineCssTextArea leftSource,
            final RecentExecutorService recentExecutorService,
            Consumer<String> formatFun,
            Consumer<String> saveFileFun,
            Consumer<Void> exitAppFun){
        ContextMenu contextMenu = buildFullRightMenu(leftSource, recentExecutorService, formatFun, saveFileFun, exitAppFun);
        leftSource.setContextMenu(contextMenu);
    }
    private static ContextMenu buildBasicRightMenu(final InlineCssTextArea leftSource,
                                                   Consumer<String> formatFun,
                                                   Consumer<String> saveFileFun,
                                                   Consumer<Void> exitAppFun){
        ContextMenu contextMenu = new ContextMenu();
        // 清空
        MenuItem clearMenu = new MenuItem("清空", new FontIcon("bi-arrow-clockwise:16"));
        clearMenu.setOnAction((ActionEvent event)-> {
            System.out.println("[SAH]CTX clear action");
            emptyEditorFun.accept(null, leftSource);
        });
        contextMenu.getItems().add(clearMenu);
        // 格式化
        MenuItem formatMenu = new MenuItem("格式化", new FontIcon("bi-braces:16"));
        formatMenu.setOnAction((ActionEvent event)-> {
            System.out.println("[SAH]CTX format action");
            formatFun.accept(leftSource.getText());
        });
        contextMenu.getItems().add(formatMenu);
        // 保存
        MenuItem saveMenu = new MenuItem("保存", new FontIcon("bi-download:16"));
        saveMenu.setOnAction((ActionEvent event)->{
            System.out.println("[SAH]CTX save action");
            saveFileFun.accept(leftSource.getText());
        });
        // 退出
        MenuItem exitMenu = new MenuItem("退出", new FontIcon("bi-arrow-bar-right:16"));
        exitMenu.setOnAction((ActionEvent event)->{
            exitAppFun.accept(null);
        });
        contextMenu.getItems().addAll(saveMenu, exitMenu);
        // 右键动作
        contextMenu.setOnAction((ActionEvent event)-> {
            System.out.println("[SAH]CTX action");
            contextMenu.hide();
        });
        return contextMenu;
    }
    private static ContextMenu buildFullRightMenu(final InlineCssTextArea leftSource,
                                                  final RecentExecutorService recentExecutorService,
                                                  Consumer<String> formatFun,
                                                  Consumer<String> saveFileFun,
                                                  Consumer<Void> exitAppFun){
        ContextMenu contextMenu = new ContextMenu();
        // 最近记录
        Menu recentRecord = new Menu("最近记录", new FontIcon("bi-clock:8"));
        Set<RecentRecord> recentRecordSet = recentExecutorService.loadRecent();
        if(recentRecordSet.isEmpty()){
            recentRecord.getItems().add(new MenuItem("暂无记录"));
        }else{
            List<MenuItem> recentRecentItem = recentRecordSet.stream().map(recentExecutorService.recentRecordMapper()).collect(Collectors.toList());
            recentRecord.getItems().addAll(recentRecentItem);
        }
        contextMenu.getItems().add(recentRecord);
        // 分隔符
        contextMenu.getItems().add(new SeparatorMenuItem());
        // 复制
        MenuItem copyMenu = new MenuItem("复制", new FontIcon("bi-file-text:8"));
        copyMenu.setOnAction((ActionEvent event)->{
            clipboardToFun.accept(leftSource);
        });
        contextMenu.getItems().add(copyMenu);
        // 粘贴
        MenuItem pasteMenu = new MenuItem("粘贴", new FontIcon("bi-clipboard:8"));
        pasteMenu.setOnAction((ActionEvent event)->{
            Object content = clipboardFromFun.apply(DataFormat.PLAIN_TEXT);
            if(null!=content) {
                emptyEditorFun.andThen(putEditorFun).accept(content.toString(), leftSource);
                // JsonResult.getInstance().setResult(content.toString());
            }
        });
        contextMenu.getItems().add(pasteMenu);
        // 分隔符1
        contextMenu.getItems().add(new SeparatorMenuItem());
        // 清空
        MenuItem clearMenu = new MenuItem("清空", new FontIcon("bi-arrow-clockwise:8"));
        clearMenu.setOnAction((ActionEvent event)-> {
            System.out.println("[SAH]CTX clear action");
            emptyEditorFun.accept(null, leftSource);
        });
        contextMenu.getItems().add(clearMenu);
        // 格式化
        MenuItem formatMenu = new MenuItem("格式化", new FontIcon("bi-braces:8"));
        formatMenu.setOnAction((ActionEvent event)-> {
            System.out.println("[SAH]CTX format action");
            formatFun.accept(leftSource.getText());
        });
        contextMenu.getItems().add(formatMenu);
        /* 树状图
        MenuItem treeMenu = new MenuItem("视图", new FontIcon("bi-diagram-3:8"));
        treeMenu.setOnAction((ActionEvent event)-> {
            System.out.println("[SAH]CTX Tree action");
        });
        contextMenu.getItems().add(treeMenu);
        // 分隔符2
        contextMenu.getItems().add(new SeparatorMenuItem());*/
        // 保存
        MenuItem saveMenu = new MenuItem("保存", new FontIcon("bi-download:8"));
        saveMenu.setOnAction((ActionEvent event)->{
            System.out.println("[SAH]CTX save action");
            saveFileFun.accept(leftSource.getText());
        });
        // 退出
        MenuItem exitMenu = new MenuItem("退出", new FontIcon("bi-arrow-bar-right:8"));
        exitMenu.setOnAction((ActionEvent event)->{
            exitAppFun.accept(null);
        });
        contextMenu.getItems().addAll(saveMenu, exitMenu);
        // 右键动作
        contextMenu.setOnAction((ActionEvent event)-> {
            System.out.println("[SAH]CTX action");
            contextMenu.hide();
        });
        return contextMenu;
    }

}
